package com.computergames.server.server.handler;

import com.computergames.server.domain.ClientState;
import com.computergames.server.domain.Deck;
import com.computergames.server.domain.MahjongTile;
import com.computergames.server.domain.PokerCard;
import com.computergames.server.message.ReadyRequestMessage;
import com.computergames.server.message.ReadyResponseMessage;
import com.computergames.server.server.session.RoomSessionFactory;
import com.computergames.server.service.Deal.DealStrategy;
import com.computergames.server.service.Deal.DealStrategyFactory;
import com.computergames.server.service.Interface.CheckAndUpdateClientState;
import com.computergames.server.util.RedisUtil;
import com.computergames.server.util.SpringUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@ChannelHandler.Sharable
public class ReadyRequestMessageHandler extends SimpleChannelInboundHandler<ReadyRequestMessage> {
    private static final ReadyRequestMessageHandler INSTANCE = new ReadyRequestMessageHandler();
    CheckAndUpdateClientState checkAndUpdateClientState;

    private static final ConcurrentHashMap<String, AtomicInteger> roomReadyCounts = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Deck> roomDecks = new ConcurrentHashMap<>();
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ReadyRequestMessage msg) throws Exception {
        String roomName = (String)channelHandlerContext.attr(AttributeKey.valueOf("USER_ROOM")).get();
        RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);
        String roomType = redisUtil.hget(roomName, "roomType").toString();
        checkAndUpdateClientState = SpringUtil.getBean(CheckAndUpdateClientState.class);
        if(checkAndUpdateClientState.checkState(channelHandlerContext, ClientState.GAME_READY)){
            AtomicInteger count = roomReadyCounts.computeIfAbsent(roomName, k -> new AtomicInteger(0));
            if(msg.isReady()){
                count.incrementAndGet();
                List<Channel> channels = RoomSessionFactory.getRoomSession()
                        .getMembersChannel(roomName);
                String member = (String)channelHandlerContext.attr(AttributeKey.valueOf("USER_IDENTIFIER")).get();
                channels.forEach(channel -> {
                    channel.writeAndFlush(new ReadyResponseMessage(true, member + "已准备," + "当前已准备人数：" + count.get() + "/" + channels.size()));
                });
                if(count.get() == channels.size()){
                    channels.forEach(channel -> {
                        checkAndUpdateClientState.updateState(channel, ClientState.GAME_STARTED);
                        channel.writeAndFlush(new ReadyResponseMessage(true, "所有人准备就绪，比赛开始"));
                    });
                    // 牌类博弈项目执行发牌方法
                    if (roomType.equals("麻将")) {
                        channels.forEach(channel -> {
                            checkAndUpdateClientState.updateState(channel, ClientState.GAME_READY);
                        });
                        DealStrategy<MahjongTile> dealStrategy = DealStrategyFactory.getDealStrategy(roomType);
                        if (dealStrategy != null) {
                            // 使用线程安全的Map来获取或创建Deck实例
                            Deck<MahjongTile> deck = roomDecks.computeIfAbsent(roomName, k -> new Deck<>(1, MahjongTile.class));
                            dealStrategy.dealCards(roomName, deck, null);
                        }
                    } else if (roomType.equals("斗地主")||roomType.equals("德州扑克")||roomType.equals("桥牌")){
                        channels.forEach(channel -> {
                            checkAndUpdateClientState.updateState(channel, ClientState.GAME_READY);
                        });
                        DealStrategy<PokerCard> dealStrategy = DealStrategyFactory.getDealStrategy(roomType);
                        if (dealStrategy != null) {
                            Deck<PokerCard> deck = roomDecks.computeIfAbsent(roomName, k -> new Deck<>(1, PokerCard.class));
                            dealStrategy.dealCards(roomName, deck, null);
                        }
                    }

                }
            }

        }
    }

    public static ReadyRequestMessageHandler getInstance() {
        return INSTANCE;
    }

    public Deck getDeckForRoom(String roomName) {
        return roomDecks.get(roomName);
    }
}
